
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>

#define DOWNLOAD_PROXY_PREFIX "https://get.2sb.org"

#define USER_AGENT "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"

static size_t write_to_file(
    void *ptr,
    size_t size,
    size_t nmemb,
    void *userdata)
{
    FILE *file = (FILE *)userdata;
    return fwrite(ptr, size, nmemb, file);
}

int init_curl()
{
    CURLcode code = curl_global_init(CURL_GLOBAL_DEFAULT);
    if (code != CURLE_OK)
    {
        fprintf(stderr, "libcurl init error: %s\n",
                curl_easy_strerror(code));
        return 1;
    }

    return 0;
}

int curl_get_to_file(const char *url,
                     const char *filename)
{
    CURL *curl = curl_easy_init();
    if (!curl)
    {
        fprintf(stderr, "curl_easy_init failed\n");
        return 1;
    }

    FILE *file = fopen(filename, "wb");
    if (!file)
    {
        fprintf(stderr, "error: open %s failed\n", filename);
        curl_easy_cleanup(curl);
        return 1;
    }
    curl_easy_setopt(curl, CURLOPT_URL, url);                     // 请求URL
    curl_easy_setopt(curl, CURLOPT_USERAGENT, USER_AGENT);        // 设置User-Agent
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);           // 跟随重定向
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_to_file); // 响应写入回调
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);              // 回调的用户数据（文件指针）
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);           // 验证SSL证书
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);           // 验证主机名
    curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);               // 显示进度（可选）
    curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, NULL);       // 使用默认进度显示
    printf("downloading: %s -> %s\n", url, filename);

    CURLcode code = curl_easy_perform(curl);
    if (code != CURLE_OK)
    {
        fprintf(stderr, "error: failed to download %s (url: %s)\n",
                curl_easy_strerror(code),
                url);
        fclose(file);
        curl_easy_cleanup(curl);
        return 1;
    }

    int http_code = 0;
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);

    if (http_code != 200)
    {
        fprintf(
            stderr,
            "http status code is not 200, current code: %d (url: %s)\n",
            http_code, url);
        fclose(file);
        remove(filename);
        curl_easy_cleanup(curl);
        return 1;
    }

    fclose(file);
    curl_easy_cleanup(curl);
    printf("done: %s\n", filename);
    return 0;
}

int main(int argc, char const *argv[])
{
    if (argc < 2)
    {
        fprintf(stderr, "Usage: %s <url>", argv[0]);
        return 1;
    }

    char prefixed_url[512];
    snprintf(prefixed_url, sizeof(prefixed_url), "https://get.2sb.org/%s", argv[1]);
    printf("prefixed url: %s\n", prefixed_url);
    const char *filename = strrchr(prefixed_url, '/');
    filename = filename ? (filename + 1) : prefixed_url;
    printf("filename is: %s\n", filename);
    if (curl_get_to_file(
            prefixed_url, filename) != 0)
    {
        fprintf(stderr, "error: failed to get to file\n");
        return 1;
    }

    printf("ok\n");

    return 0;
}
